﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//引入串口使用的命名空间
using System.IO.Ports;

namespace SerialPortHelper
{
    /// <summary>
    /// 串口助手通用类
    /// </summary>
    public class SerialPortHelperPro
    {
    
        #region  相关属性

        //创建一个串口操作对象
        private SerialPort serialPort = null;
        public SerialPort SerialPortObject
        {
            get { return serialPort; }
        }
        //串口状态
        public bool IsOpen
        {
            get { return serialPort.IsOpen; }
        }
        //当前串口名
        public string PortName
        {
            get { return serialPort.PortName; }
        }
        /// <summary>
        /// 当前计算机上的可用端口名称列表【只读】
        /// </summary>
        public string[] PortNames
        {
            get { return System.IO.Ports.SerialPort.GetPortNames(); }
        }

        /// <summary>
        /// 进制转换对象
        /// </summary>
        private AlgorithmHelper algorithmHelper = null;
        public AlgorithmHelper AlgorithmHelperObject
        {
            get { return algorithmHelper; }
        }

        #endregion

        /// <summary>
        /// 构造方法中初始化端口默认数据
        /// </summary>
        public SerialPortHelperPro()
        {
            this.serialPort = new SerialPort();
            //串口基本参数初始化        
            this.serialPort.BaudRate = 9600; //波特率默认9600
            this.serialPort.Parity = System.IO.Ports.Parity.None; //校验位默认NONE
            this.serialPort.DataBits = 8; //数据位默认为8
            this.serialPort.StopBits = System.IO.Ports.StopBits.One; //停止位默认为1

            //初始化进制转换对象
            this.algorithmHelper = new AlgorithmHelper();
        }

        #region 打开或关闭端口

        /// <summary>
        /// 根据端口名称打开或关闭端口
        /// </summary>
        /// <param name="portName">端口名称</param>
        /// <param name="status">端口操作：1，打开，0，关闭</param>
        /// <returns></returns>
        public bool OpenSerialPort(string portName, int status)
        {
            if (status == 1)
            {
                this.serialPort.PortName = portName;//只有在端口没有打开的时候才能设置端口名称 
                this.serialPort.Open();
            }
            else
            {
                this.serialPort.Close();
            }
            return this.serialPort.IsOpen;   //返回串口打开的状态 
        }

        #endregion

        #region 发送数据

        /// <summary>
        /// 判断十六进制字符串hex是否正确
        /// </summary>
        /// <param name="hex">十六进制字符串</param>
        /// <returns>true：不正确，false：正确</returns>
        private bool IsIllegalHex(string hex)
        {
            return System.Text.RegularExpressions.Regex.IsMatch(hex, @"([^A-Fa-f0-9]|\s+?)+");
        }
        /// <summary>
        /// 发送数据【可以是16进制，也可以是字符串】
        /// </summary>
        /// <param name="data">发送的数据</param>
        /// <param name="format">发送的格式</param>
        public void SendData(string data, SendFormat format)
        {
            if (this.serialPort.IsOpen == false)
            {
                throw new Exception("端口未打开，请打开端口！");//让调用者处理
            }
            else
            {
                byte[] byteData;
                if (format == SendFormat.Hex)//如果是16进制
                {
                    if (this.IsIllegalHex(data))                        
                        byteData = algorithmHelper.From16ToBtyes(data);//将16进制转换成byte[]数组
                    else
                        throw new Exception("数据不是16进制格式！");
                }
                else //发送字符串
                {
                    byteData = algorithmHelper.StringToBytes(data, false);
                }
                this.serialPort.Write(byteData, 0, byteData.Length);//发送数据（数据，从0开始，结束位置）
            }
        }
        #endregion

        #region 接收数据
        public byte[] StartReceiveData()
        {
            int n = this.serialPort.BytesToRead;
            byte[] bytData = new byte[n];//定义一个接收数组，获取接收缓冲区中数据的字节数。
            this.serialPort.Read(bytData, 0, n);//读取数据
            return bytData;
        }
        #endregion

    }
    /// <summary>
    /// 发送格式选择【16进制或字符串】
    /// </summary>
    public enum SendFormat
    {
        Hex,//十六进制
        String
    }
}
